package com.xnyzc.lhy.mis.service.impl.activity;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.xnyzc.lhy.common.exception.ActivityException;
import com.xnyzc.lhy.common.penum.activity.ActivityErrorCode;
import com.xnyzc.lhy.common.util.DateUtil;
import com.xnyzc.lhy.common.util.IDUtil;
import com.xnyzc.lhy.common.util.TokenUtil;
import com.xnyzc.lhy.mis.entity.activity.OaSysActivityPeriod;
import com.xnyzc.lhy.mis.entity.activity.OaSysActivityReward;
import com.xnyzc.lhy.mis.entity.activity.OaSysActivityRewardRule;
import com.xnyzc.lhy.mis.entity.driver.wallet.OaDWallet;
import com.xnyzc.lhy.mis.entity.driver.wallet.OaDWalletRecord;
import com.xnyzc.lhy.mis.entity.param.activity.DriverOnLineTimeParam;
import com.xnyzc.lhy.mis.entity.result.activity.ActivityRewardResult;
import com.xnyzc.lhy.mis.entity.result.activity.DriverOnLineTimeResult;
import com.xnyzc.lhy.mis.mapper.activity.OaSysActivityRewardMapper;
import com.xnyzc.lhy.mis.mapper.driver.wallet.OaDWalletMapper;
import com.xnyzc.lhy.mis.mapper.driver.wallet.OaDWalletRecordMapper;
import com.xnyzc.lhy.mis.mapper.work.OaDWorkRecordMapper;
import com.xnyzc.lhy.mis.service.account.IOaDAccountAdjustmentService;
import com.xnyzc.lhy.mis.service.activity.IOaSysActivityRewardRuleService;
import com.xnyzc.lhy.mis.service.activity.IOaSysActivityRewardService;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.math.BigDecimal;
import java.time.format.DateTimeFormatter;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.UUID;
import java.util.stream.Collectors;

/**
 * <p>
 * 活动结果 服务实现类
 * </p>
 *
 * @author haoyfa
 * @since 2019-12-16
 */
@Service
@Slf4j
public class OaSysActivityRewardServiceImpl extends ServiceImpl<OaSysActivityRewardMapper, OaSysActivityReward> implements IOaSysActivityRewardService {

    @Autowired
    OaSysActivityRewardMapper oaSysActivityRewardMapper;

    @Autowired
    IOaSysActivityRewardRuleService iOaSysActivityRewardRuleService;

    @Autowired
    OaDWorkRecordMapper oaDWorkRecordMapper;

    @Autowired
    OaDWalletMapper oaDWalletMapper;

    @Autowired
    OaDWalletRecordMapper oaDWalletRecordMapper;

    @Autowired
    IOaDAccountAdjustmentService iOaDAccountAdjustmentService;

    /**
     * 根据活动周期id获取活动奖励结果result
     * @param periodId
     * @return
     */
    @Override
    public List<ActivityRewardResult> queryActivityRewardResultList(String periodId) {
        if(StringUtils.isEmpty(periodId)){
            throw new ActivityException(ActivityErrorCode.periodEmptyError);
        }

        return oaSysActivityRewardMapper.queryActivityRewardResultList(Long.parseLong(periodId));
    }

    /**
     * 根据活动周期id获取活动奖励结果
     * @param periodId
     * @return
     */
    @Override
    public List<OaSysActivityReward> queryActivityRewardList(Long periodId) {
        QueryWrapper<OaSysActivityReward> activityRewardQueryWrapper = new QueryWrapper<OaSysActivityReward>();
        activityRewardQueryWrapper.eq(OaSysActivityReward.PERIOD_ID, periodId);

        return oaSysActivityRewardMapper.selectList(activityRewardQueryWrapper);
    }

    /**
     * 创建活动奖励结果
     * @param
     * @return
     */
    @Override
    public List<OaSysActivityReward> createActivityReward(OaSysActivityPeriod oaSysActivityPeriod, String cityIds, Integer withinDate) {
        //获取活动规则
        List<OaSysActivityRewardRule> oaSysActivityRewardRule =
                iOaSysActivityRewardRuleService.queryActivityRewardRuleList(oaSysActivityPeriod.getDefId());

        if(oaSysActivityRewardRule == null
                && oaSysActivityRewardRule.size() <= 0){
            throw new ActivityException(ActivityErrorCode.ruleEmptyError);
        }

        List<DriverOnLineTimeResult> driverSumList = this.getDriverSum(oaSysActivityPeriod, cityIds, withinDate);

        if(driverSumList != null
                && driverSumList.size() >= 0) {

            //推荐人规则
            List<OaSysActivityRewardRule> fromDriverRuleList =
                    oaSysActivityRewardRule.stream().filter(item -> "00".equals(item.getDriverFrom())).collect(Collectors.toList());

            //被推荐人规则
            List<OaSysActivityRewardRule> toDriverRule =
                    oaSysActivityRewardRule.stream().filter(item -> "01".equals(item.getDriverFrom())).collect(Collectors.toList());


            //奖励列表
            List<OaSysActivityReward> oaSysActivityRewardList = null;
            //创建推荐人奖励
            for (DriverOnLineTimeResult driverSum: driverSumList) {
                // 推荐人规则
                if(fromDriverRuleList != null
                        && fromDriverRuleList.size() > 0){
                    OaSysActivityRewardRule fromDriverRule = null;

                    for (int i = fromDriverRuleList.size() - 1; i >=0; i--) {
                        OaSysActivityRewardRule activityRewardRule = fromDriverRuleList.get(i);

                        //00=完成订单量；01=订单流水金额；02=出车时长。
                        switch (activityRewardRule.getRewardType()) {
                            case "00":
                                int orderCountValue = (new BigDecimal(driverSum.getSumOrderCount())).compareTo(activityRewardRule.getRewardNumber());
                                if(orderCountValue == 1 || orderCountValue == 0){
                                    fromDriverRule = activityRewardRule;
                                }
                                break;
                            case "01":
                                int orderDrawFeeValue = (new BigDecimal(driverSum.getSumOrderDrawFee())).compareTo(activityRewardRule.getRewardNumber());
                                if(orderDrawFeeValue == 1 || orderDrawFeeValue == 0){
                                    fromDriverRule = activityRewardRule;
                                }
                                break;
                            case "02":
                                int onlineValue = (new BigDecimal(driverSum.getSumSecond())).compareTo(activityRewardRule.getRewardNumber());
                                if(onlineValue == 1 || onlineValue == 0){
                                    fromDriverRule = activityRewardRule;
                                }
                                break;
                            default:
                                break;
                        }

                        //找到规则
                        if(fromDriverRule != null){
                            break;
                        }
                    }

                    if(fromDriverRule != null) {
                        //创建活动结果
                        OaSysActivityReward oaSysActivityReward = new OaSysActivityReward();
                        Long id = IDUtil.nextId();
                        oaSysActivityReward.setId(id);
                        oaSysActivityReward.setDriverFrom(fromDriverRule.getDriverFrom());
                        oaSysActivityReward.setDriverId(Long.parseLong(driverSum.getDriverId()));
                        oaSysActivityReward.setPeriodId(oaSysActivityPeriod.getId());
                        oaSysActivityReward.setRuleId(fromDriverRule.getId());
                        oaSysActivityReward.setRewardAmount(fromDriverRule.getRewardAmount());
                        oaSysActivityReward.setRewardOrder(driverSum.getOrderNos());
                        oaSysActivityReward.setRewardOnlineRecord(driverSum.getRecordIds());

                        Date date = new Date();
                        oaSysActivityReward.setCreateTime(date);
                        oaSysActivityReward.setCreateUser(TokenUtil.getTokenUserId());
                        oaSysActivityReward.setDeleted(0);
                        oaSysActivityReward.setVersion(0L);
                        oaSysActivityReward.setUpdateTime(date);

                        oaSysActivityRewardMapper.insert(oaSysActivityReward);

                        if (oaSysActivityRewardList == null) {
                            oaSysActivityRewardList = new ArrayList<OaSysActivityReward>();
                        }
                        oaSysActivityRewardList.add(oaSysActivityReward);
                    } else {
                        log.info("活动周期内没有活动推荐人规则");
                        //什么都做，继续计算其他奖励
                        continue;
                    }
                }
                else{
                    log.info("活动周期内没有活动推荐人规则");
                    //什么都做，继续计算其他奖励
                    continue;
                }
            }

            return oaSysActivityRewardList;
        }
        else{
            log.info("在活动周期内，没有找到符合条件的司机。");
            //什么都做
            return null;
        }
    }

    /**
     * 结算司机奖励
     * @param oaSysActivityRewardList
     */
    @Override
    public void calDriverReward(List<OaSysActivityReward> oaSysActivityRewardList){
        //当前时间
        Date date = new Date();
        //费用说明
        StringBuilder amountRemark = new StringBuilder();
        for (OaSysActivityReward oaSysActivityReward : oaSysActivityRewardList)
        {
            amountRemark.append("司机活动")
                    .append("向司机【")
                    .append(oaSysActivityReward.getDriverId())
                    .append("】发起结算奖励。");

            //调整金额
            BigDecimal rewardAmount = oaSysActivityReward.getRewardAmount();

            OaDWallet oaDWallet =
                    oaDWalletMapper.selectOne(
                            Wrappers.<OaDWallet>lambdaQuery().eq(OaDWallet::getDriverId, oaSysActivityReward.getDriverId()));

            if (oaDWallet != null)
            {
                //钱包余额 = 可提现金额 + 冻结金额，如果操作了冻结金额或者可提现金额，都要同步修改钱包余额
                //向上的账户调整，即为向“冻结余额”内打钱
                amountRemark.append(
                        "向“冻结余额”内打" + rewardAmount + "元，");
                oaDWallet.setWalletBalance(oaDWallet.getWalletBalance().add(rewardAmount));
                oaDWallet.setFrozenBalance(oaDWallet.getFrozenBalance().add(rewardAmount));
                oaDWalletMapper.updateById(oaDWallet);
                amountRemark.append("现余额").append(oaDWallet.getCashBalance());

                //创建冻结金额记录表数据
                iOaDAccountAdjustmentService.saveFreezeBalance(oaDWallet.getDriverId(), rewardAmount);

                //添加钱包明细表   交易流水号规则 SJZHTZ + YYYYMMdd + 十位随机数
                OaDWalletRecord oaDWalletRecord = new OaDWalletRecord();
                oaDWalletRecord.setRecordId(IDUtil.nextId());
                oaDWalletRecord.setDriverId(oaDWallet.getDriverId());
                oaDWalletRecord.setAmount(rewardAmount);
                //活动奖励
                oaDWalletRecord.setRecordType(12);
                oaDWalletRecord.setTransactionTime(date);
                oaDWalletRecord.setTransactionSerialNo(
                        "SJHDJL" + DateUtil.getDateDay().replaceAll("-", "") +
                                UUID.randomUUID().toString().replace("-", "").substring(0, 9));
                oaDWalletRecord.setAmountRemark(amountRemark.toString());
                oaDWalletRecord.setTag("lhy");
                oaDWalletRecord.setCreateUser(oaSysActivityReward.getCreateUser());
                oaDWalletRecord.setCreateTime(date);
                oaDWalletRecord.setUpdateUser(oaSysActivityReward.getCreateUser());
                oaDWalletRecord.setUpdateTime(date);
                oaDWalletRecordMapper.insert(oaDWalletRecord);

                //创建司机流水=活动奖励
                iOaDAccountAdjustmentService.saveActivityOaDBill("", rewardAmount, oaDWallet.getDriverId());
            }
        }
    }

    /**
     * 创建活动结果记录
     * @param driverSum
     */
    private void createActivityReward(List<OaSysActivityRewardRule> driverRuleList, DriverOnLineTimeResult driverSum){

    }

    /**
     * 获取司机统计信息，包括在线时长、订单合计、订单金额合计
     * @param oaSysActivityPeriod
     * @param cityIds
     * @return
     */
    private List<DriverOnLineTimeResult> getDriverSum(OaSysActivityPeriod oaSysActivityPeriod, String cityIds, Integer withinDate){
        List<DriverOnLineTimeResult> onlineSum = this.getDriverOnLineTime(oaSysActivityPeriod, cityIds, withinDate);
        List<DriverOnLineTimeResult> orderSum = this.getDriverOrderSum(oaSysActivityPeriod, cityIds, withinDate);

        List<DriverOnLineTimeResult> driverSum = null;
        if(onlineSum != null
                && onlineSum.size() > 0){
            for (DriverOnLineTimeResult online : onlineSum) {
                if (orderSum != null
                        && orderSum.size() > 0) {
                    //匹配订单合计和订单金额合计
                    for (DriverOnLineTimeResult order : orderSum) {
                        if (online.getDriverId() != null
                        && online.getDriverId().equals(order.getDriverId())) {
                            //订单合计
                            online.setSumOrderCount(order.getSumOrderCount());
                            //订单金额合计
                            online.setSumOrderDrawFee(order.getSumOrderDrawFee());
                            //订单NO
                            online.setOrderNos(order.getOrderNos());
                        }
                    }
                }

                //如果没有找到订单数据，设置值为0
                //订单合计
                if(online.getSumOrderCount() == null){
                    online.setSumOrderCount("0");
                }

                if(online.getSumOrderDrawFee() == null){
                    //订单金额合计
                    online.setSumOrderDrawFee("0");
                }
            }

            driverSum = onlineSum;

            return driverSum;
        }
        else {
            return null;
        }
    }

    /**
     * 获取司机在线时长
     * @param oaSysActivityPeriod 周期内
     * @param cityIds 城市id集合，以","分割
     * @return
     */
    private List<DriverOnLineTimeResult> getDriverOnLineTime(OaSysActivityPeriod oaSysActivityPeriod, String cityIds, Integer withinDate){
        DriverOnLineTimeParam driverOnLineTimeParam = new DriverOnLineTimeParam();
        //开始日期
        driverOnLineTimeParam.setStrartDate(oaSysActivityPeriod.getBeginDate().toString());
        //结束日期=结束日期+1天
        driverOnLineTimeParam.setEndDate(oaSysActivityPeriod.getEndDate().plusDays(1).toString());
        //开始时间
        driverOnLineTimeParam.setStartTime(oaSysActivityPeriod.getBeginTime().format(DateTimeFormatter.ofPattern("HH:mm:ss")));
        //结束时间
        driverOnLineTimeParam.setEndTime(oaSysActivityPeriod.getEndTime().format(DateTimeFormatter.ofPattern("HH:mm:ss")));
        //城市范围
        driverOnLineTimeParam.setCityIds(cityIds);

        //司机几日内激活
        driverOnLineTimeParam.setWithinDate(withinDate);

        //获取司机在线时长
        return oaSysActivityRewardMapper.getDriverOnLineTimeSum(driverOnLineTimeParam);
    }

    /**
     * 获取司机订单数合计和订单金额合计
     * @param oaSysActivityPeriod 周期内
     * @param cityIds 城市id集合，以","分割
     * @return
     */
    private List<DriverOnLineTimeResult> getDriverOrderSum(OaSysActivityPeriod oaSysActivityPeriod, String cityIds, Integer withinDate){
        DriverOnLineTimeParam driverOnLineTimeParam = new DriverOnLineTimeParam();
        //开始日期
        driverOnLineTimeParam.setStrartDate(oaSysActivityPeriod.getBeginDate().toString());
        //结束日期=结束日期+1天
        driverOnLineTimeParam.setEndDate(oaSysActivityPeriod.getEndDate().plusDays(1).toString());
        //开始时间
        driverOnLineTimeParam.setStartTime(oaSysActivityPeriod.getBeginTime().format(DateTimeFormatter.ofPattern("HH:mm:ss")));
        //结束时间
        driverOnLineTimeParam.setEndTime(oaSysActivityPeriod.getEndTime().format(DateTimeFormatter.ofPattern("HH:mm:ss")));
        //城市范围
        driverOnLineTimeParam.setCityIds(cityIds);

        //司机几日内激活
        driverOnLineTimeParam.setWithinDate(withinDate);

        //获取司机在线时长
        return oaSysActivityRewardMapper.getDriverOrderSum(driverOnLineTimeParam);
    }
}
